package com.health.trans.pojo;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.extra.cglib.CglibUtil;
import org.hibernate.query.NativeQuery;
import org.hibernate.transform.Transformers;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaQuery;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author nqlz
 */
public class JpaHelper {

    private final EntityManager entityManager;

    public JpaHelper(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    public <T> void saveOrUpdate(T t) {
        T dbT = entityManager.find(ClassUtil.getClass(t), t);
        if (Objects.nonNull(dbT)) {
            entityManager.merge(t);
        } else {
            entityManager.persist(t);
        }
    }

    public <T> List<T> search(Class<T> tClass, String sql) {
        return searchMaps(sql).stream().map(i -> CglibUtil.toBean(i, tClass)).collect(Collectors.toList());
    }

    public <T> T searchOne(Class<T> tClass, String sql) {
        Query query = entityManager.createNativeQuery(sql).unwrap(NativeQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        Object singleResult = query.getSingleResult();
        return Objects.isNull(singleResult) ? null : Convert.convert(tClass, singleResult);
    }

    public <T> T searchOne(Class<T> tClass, CriteriaQuery<Object> criteriaQuery) {
        Query query = entityManager.createQuery(criteriaQuery).unwrap(NativeQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        Object singleResult = query.getSingleResult();
        return Objects.isNull(singleResult) ? null : Convert.convert(tClass, singleResult);
    }

    public <T, V> List<Map<T, V>> searchMaps(String sql) {
        Query query = entityManager.createNativeQuery(sql).unwrap(NativeQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        return (List<Map<T, V>>) query.getResultList();
    }

    public Long count(String sql) {
        return Long.valueOf(entityManager.createNativeQuery(sql).getSingleResult().toString());
    }

    public boolean exit(String sql) {
        return count(sql) > 0L;
    }

    public <T> List<T> singleColumn(String sql) {
        return (List<T>) entityManager.createNativeQuery(sql).getResultList();
    }

}

